#include <stdbool.h>
#include <stdint.h>
#include "esp32c3_init.h"


extern char __bss_start;
extern char __bss_end;
char *bss_start = &__bss_start;
char *bss_end = &__bss_end;

void wdt_disable(void)
{
	REG(C3_RTCCNTL)[42] = 0x50d83aa1;  // Disable write protection
	// REG(C3_RTCCNTL)[36] &= BIT(31);    // Disable RTC WDT
	REG(C3_RTCCNTL)[36] = 0;  // Disable RTC WDT
	REG(C3_RTCCNTL)[35] = 0;  // Disable

	// bootloader_super_wdt_auto_feed()
	REG(C3_RTCCNTL)[44] = 0x8F1D312A;
	REG(C3_RTCCNTL)[43] |= BIT(31);
	REG(C3_RTCCNTL)[45] = 0;

	REG(C3_TIMERGROUP0)[63] &= ~BIT(9);  // TIMG_REGCLK -> disable TIMG_WDT_CLK
	REG(C3_TIMERGROUP0)[18] = 0;         // Disable TG0 WDT
	REG(C3_TIMERGROUP1)[18] = 0;         // Disable TG1 WDT
}

void soc_init(void)
{
	// Init clock. TRM 6.2.4.1
	REG(C3_SYSTEM)[2] &= ~3U;
	REG(C3_SYSTEM)[2] |= BIT(0) | BIT(2);
	REG(C3_SYSTEM)[22] = BIT(19) | (40U << 12) | BIT(10);
	// REG(C3_RTCCNTL)[47] = 0; // RTC_APB_FREQ_REG -> freq >> 12
	((void (*)(int)) 0x40000588)(160);  // ets_update_cpu_frequency(160)
}

void bss_clear(void)
{
	char *p = 0;

	for (p = bss_start; p < bss_end; p++) {
		*p = 0;
	}
}

static void gpio_output_enable(int pin, bool enable)
{
	REG(C3_GPIO)[GPIO_OUT_EN] &= ~BIT(pin);
	REG(C3_GPIO)[GPIO_OUT_EN] |= (enable ? 1U : 0U) << pin;
}

void gpio_output(int pin)
{
	REG(C3_GPIO)[GPIO_OUT_FUNC + pin] = BIT(9) | 128; // Simple out, TRM 5.5.3
	gpio_output_enable(pin, 1);
}

void gpio_write(int pin, bool value)
{
  REG(C3_GPIO)[1] &= ~BIT(pin); // Clear first
  REG(C3_GPIO)[1] |= (value ? 1U : 0U) << pin; // Then set
}